require 'pictopus'

module Pictopus
  class Gradient
    OPTION_KEYS = [:start_color, :end_color, :orientation, :size, :format]
    
    # Provide some default options for
    # generating gradients. You shouldn't
    # ever really see this unless you're
    # hacking on something custom.
    def self.default_options
      @options ||= {
        :size => '100x100',
        :format => 'png',
        :orientation => 'vertical',
        :start_color => 'fff',
        :end_color => '000'
      }
    end
    
    # Create a new Gradient object and provide
    # options. The available options are enumerated
    # in OPTION_KEYS.
    def initialize(options = {})
      @options = self.class.default_options.merge(options)
    end
    
    # Convert this object to a string of command line arguments
    # acceptable by ImageMagick.
    def to_args
      args = []
      args << "-size #{parse_size(size)}"
      args << "gradient:#{parse_color(start_color)}-#{parse_color(end_color)}"
      args << "-rotate -90" if horizontal?
      args << File.join(output_directory, file_name)
      args.join(' ')
    end
    
    # Run the actual command to generate the image
    # for this instance.
    def run!
      FileUtils.mkdir_p(output_directory) unless File.directory?(File.dirname(output_directory))
      Pictopus.run('convert', self.to_args)
    end
    
    OPTION_KEYS.each do |opt|
      class_eval <<-RUBY
      def #{opt}
        @options[#{opt.inspect}]
      end
      
      def #{opt}=(value)
        @options[#{opt.inspect}] = value
      end
      RUBY
    end
    
    # True if the image is set to be a vertical gradient.
    def vertical?
      %w(v vertical).include?(orientation)
    end

    # True if the image is set to be a horizontal gradient.    
    def horizontal?
      %w(h horizontal).include?(orientation)
    end
    
    def output_directory # :nodoc:
      File.join(@options[:output_path], 'images', 'pictopus', 'gradient')
    end
    
    def file_name # :nodoc:
      [start_color, end_color, orientation, size, format].join('.')
    end
    
    protected
    
    def parse_color(color_string)
      if color_string =~ /[0-9a-f]{3}/i || 
         color_string =~ /[0-9a-f]{6}/i || 
         color_string =~ /[0-9a-f]{8}/i
         "##{color_string}".downcase
      end
    end
    
    def parse_size(size_string)
      dimensions = size_string.split('x')
      
      case dimensions.size
        when 2
          dimensions.reverse! if horizontal?
        when 1
          dimensions.unshift('1')
      end

      dimensions.join('x')
    end
  end
end